package com.andnnl.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.*;

import java.util.List;
import java.util.Map;

/**
 * Created by chenss on 2020/8/29.
 */
public class RedisServiceImpl implements IRedisService {
    private static final Logger logger = LoggerFactory.getLogger(RedisServiceImpl.class);
    //redis server config
//    private String serverIp;
//    private int port;
    private static final int maxActive = 1000;
    private static final int maxIdle = 10;
    private static final int maxWait = 5000;
    private static final boolean testOnBorrow = true;
    private static final boolean testOnReturn = true;
    private static JedisPool pool = null;
    private static JedisPool poolRead = null;
    private Jedis jedis;

    public RedisServiceImpl(Jedis jedis) {
        this.jedis = jedis;
    }


    /***
     * 获取JedisPool对象.
     * zzz
     *
     * @return
     */
    public synchronized static IRedisService getRedisService(String serverIp, int port) {
        if (null == pool) {
            JedisPoolConfig config = getJedisPoolConfig();
            pool = new JedisPool(config, serverIp, port);
        }
        return new RedisServiceImpl(pool.getResource());
    }

    public synchronized static IRedisService getRedisReadService(String serverIp, int portRead) {
        if (null == poolRead) {
            JedisPoolConfig config = getJedisPoolConfig();
            poolRead = new JedisPool(config, serverIp, portRead);
        }
        return new RedisServiceImpl(poolRead.getResource());
    }

    private static JedisPoolConfig getJedisPoolConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        //高版本
        //连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
//        config.setBlockWhenExhausted(true);
        //最大连接数
        config.setMaxTotal(maxActive);
        //最大空闲连接数
        config.setMaxIdle(maxIdle);
        //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间,  默认-1
        config.setMaxWaitMillis(maxWait);
//        config.setMaxWaitMillis(-1);
        //在获取连接的时候检查有效性, 默认false
        config.setTestOnBorrow(testOnBorrow);
        config.setTestOnReturn(testOnReturn);
        return config;
    }


    /***
     * 根据key 获取String值
     *
     * @param key
     * @return
     */
    @Override
    public String get(String key) {
        String result = null;
        if (null != key) {
            result = jedis.get(key);

        }
        return result;
    }

    /***
     * 给key设置对象值
     *
     * @param key
     * @param value 只能是String和Map类型
     */
    @Override
    public String set(String key, Object value) {
        return set(key, value, null);
    }

    /***
     * 给key 设置对象值，并给予过期时间
     *
     * @param key
     * @param value
     * @param seconds
     */
    @Override
    public String set(String key, Object value, Integer seconds) {
        if (null != key) {
            if (null != value) {
                if (value instanceof String) {
                    String o = (String) value;
                    if (null == seconds) {
                        return jedis.set(key, o);
                    } else {
                        return jedis.setex(key, seconds, o);
                    }
                } else if (value instanceof Map) {
                    Map<String, String> valueMap = (Map<String, String>) value;
                    return jedis.hmset(key, valueMap);
                } else {
//                    new RuntimeException("redis set value must be a String or Map");
                    String o = value.toString();
                    if (null == seconds) {
                        return jedis.set(key, o);
                    } else {
                        return jedis.setex(key, seconds, o);
                    }
                }
            }

        }
        return "";
    }

    /***
     * 判断key是否存在
     * @param key
     * @return
     */
    @Override
    public boolean existsKey(String key) {
        if (null != key && jedis.exists(key))
            return true;
        return false;
    }

    /***
     *删除key
     *
     * @param key
     * @return
     */
    @Override
    public Long del(String key) {
        if (null != key && jedis.exists(key)) {
            return jedis.del(key);
        }
        return (long) -1;
    }


    /***
     * 释放redis对象
     */
    @Override
    public void destroy() {
        if (this.jedis != null)
            this.jedis.close();
    }

    @Override
    public void lpush(String key, String val) {

        jedis.lpush(key, val);
    }

    @Override
    public void expire(String key, int seconds) {

        jedis.expire(key, seconds);
    }

    @Override
    public List lrange(String key, int start, int stop) {

        return jedis.lrange(key, start, stop);
    }

    @Override
    public Long hset(String key, String field, String value) {
        return this.jedis.hset(key, field, value);
    }

    @Override
    public String hget(String key, String field) {
        return this.jedis.hget(key, field);
    }

    @Override
    public Map<String, String> hgetAll(final String key) {
        return this.jedis.hgetAll(key);
    }

    @Override
    public long incr(String key) {
        return this.jedis.incr(key);
    }

    @Override
    public long incrBy(String key, long field) {
        return this.jedis.incrBy(key, field);
    }

    @Override
    public long decr(String key) {
        return this.jedis.decr(key);
    }

    @Override
    public long decrBy(String key, long field) {
        return this.jedis.decrBy(key, field);
    }

    /**
     * 以秒为单位，返回给定 key 的剩余生存时间，
     *
     * @param key
     * @return 当 key 不存在时，返回 -2 。 当 key 存在但没有设置剩余生存时间时，返回 -1 。
     * 否则，以秒为单位，返回 key 的剩余生存时间。
     */
    @Override
    public long ttl(String key) {
        return this.jedis.ttl(key);
    }


    @Override
    public Long publish(String key,String value) {
        return this.jedis.publish(key,value);
    }
    @Override
    public Long publish(byte[] key, byte[] value) {
        return this.jedis.publish(key,value);
    }
    @Override
    public void subscribe(JedisPubSub jedisPubSub, String... channels){
        this.jedis.subscribe(jedisPubSub,channels);
    }
    @Override
    public void subscribe(BinaryJedisPubSub jedisPubSub, byte[]... channels) {
        this.jedis.subscribe(jedisPubSub,channels);
    }
    @Override
    public void psubscribe(JedisPubSub jedisPubSub, String... patterns){
        this.jedis.psubscribe(jedisPubSub,patterns);
    }
    @Override
    public void psubscribe( BinaryJedisPubSub jedisPubSub,  byte[]... patterns) {
        this.jedis.psubscribe(jedisPubSub,patterns);
    }
}
